﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using blackhouse.Aparts.Web.Modules;
using blackhouse.BlackApart.Business;
using blackhouse.BlackApart.Business.Apartments;
using blackhouse.BlackApart.Business.ApartmentServices;
using blackhouse.BlackApart.Business.Payments;
using blackhouse.BlackApart.Business.Prices;
using blackhouse.BlackApart.Business.Reservations;
using blackhouse.BlackApart.Web;
using blackhouse.BlackApart.Web.Modules;
using blackhouse.BlackApart.Web.Navigation;
using blackhouse.Currencies;
using blackhouse.JavaScript.JQuery;
using blackhouse.mojoPortalExtend;
using blackhouse.mojoPortalExtend.Breadcrumbs;
using blackhouse.Payments;
using mojoPortal.Web;

namespace blackhouse.Aparts.Web.Pages {
    public partial class OnlineReservation : NonCmsBasePage {

        #region Fields

        private const string PARAM_INFORMATION = "informacja";
        private const string PARAM_CONTACT = "kontakt";
        private const string PARAM_SERVICES = "uslugi-dodatkowe";
        private const string PARAM_PAYMENT = "platnosc";
        private const string PARAM_END = "koniec";
        private const string PARAM_CONFIRM = "potwierdzenie";
        private const string PARAM_PAY = "payu";
        private const string PARAM_STATUS = "status";

        private Factory factory = Factory.Instance();
        private Variant variant;

        protected int activePage;
        private bool error;

        private IWebReservation reservation;
        private ReservationPrice reservationPriceCalculator;

        private IAdditionalService[] additionalServices;
        private Currency reservationPrice;

        private IPaymentType[] paymentTypes;
        private double additionalServicesCost;

        private BreadcrumbsAccess breadcrumb;

        private PayUConfig payConfig;
        private PaymentTransaction transaction;

        private IApartmentGroup statusApartmentGroup;
        private int statusMaxPersons;

        #endregion

        #region Event Handlers

        protected override void OnPreInit(EventArgs e) {
            this.AllowSkinOverride = true;
            HttpContext.Current.Items.Add("skin", "blackhouse");
            HttpContext.Current.Items.Add("short-top", true);
            HttpContext.Current.Items.Add("hide-footer", true);

            base.OnPreInit(e);
        }

        protected override void OnInit(EventArgs e) {
            base.OnInit(e);
            this.AddClassToBody("short-top");
        }

        protected override void OnLoad(EventArgs e) {
            base.OnLoad(e);

            if (!IsPostBack) {
                this.SetScenario();
                this.PopulateView();
            }
        }

        #endregion

        #region Methods

        private void SetPageSeo() {
            PageProvider pp = new PageProvider();
            mojoPortal.Business.PageSettings p = pp.FindCmsPageByFunctionality("reservation");
            if (p != null) {
                pp.TrySetFromCms(p);
                this.breadcrumb = new BreadcrumbsAccess();
                breadcrumb.AddCrumb(p.PageName, NavigationProvider.Instance().GetUrl(ReservationPage.GetInformationPage(0)));
            }
        }

        private void SetScenario() {
            if (Request.QueryString["step"] == PARAM_INFORMATION) {
                if (!this.SetScenarioForInformation()) {
                    this.error = true;
                    return;
                }
            }
            if (Request.QueryString["step"] == PARAM_CONTACT) {
                if (!this.SetScenarioForContact()) {
                    this.error = true;
                    return;
                }
            }
            if (Request.QueryString["step"] == PARAM_SERVICES) {
                if (!this.SetScenarioForAdditionalServices()) {
                    this.error = true;
                    return;
                }
            }

            if (Request.QueryString["step"] == PARAM_PAYMENT) {
                if (!this.SetScenarioForPayments()) {
                    this.error = true;
                    return;
                }
            }
            if (Request.QueryString["step"] == PARAM_END) {
                if (!this.SetScenarioForPayments()) {
                    this.error = true;
                    return;
                }
            }
            if (Request.QueryString["step"] == PARAM_CONFIRM) {
                if (!this.SetScenarioForConfirm()) {
                    this.error = true;
                    return;
                }
            }
            if (Request.QueryString["step"] == PARAM_PAY) {
                if (!this.SetScenarioForPay()) {
                    this.error = true;
                    return;
                }
            }
            if (Request.QueryString["step"] == PARAM_STATUS) {
                if (!this.SetScenarioForStatus()) {
                    this.error = true;
                    return;
                }
            }
        }

        private bool SetReservationFromRequest() {
            string sGuid = Request["reservation"];
            if (string.IsNullOrEmpty(sGuid)) return false;
            Guid guid = Guid.Empty;
            if (Guid.TryParse(sGuid, out guid)) {
                this.reservation = this.factory.GetWebReservation(guid);
                this.reservationPriceCalculator = new ReservationPrice(this.reservation);
                return this.reservation.Guid == guid;
            }
            else return false;
        }

        private bool SetScenarioForAdditionalServices() {
            if (this.SetReservationFromRequest()) {
                this.additionalServices = factory.GetAdditionalService().GetServicesForReservation(this.reservation.ReservationId);
                DisplayCurrency dc = new DisplayCurrency(this.reservation.Price, 2);
                dc.Load();
                this.reservationPrice = dc.Currency;
                return true;
            }
            else
                return false;
        }

        private bool SetScenarioForEnd() {
            return this.SetReservationFromRequest();
        }

        private bool SetScenarioForConfirm() {
            if (this.SetReservationFromRequest()) {
                this.reservation.ChangeStatus("confirm");
                return true;
            }
            else return false;

        }

        private bool SetScenarioForPay() {
            if (this.SetReservationFromRequest()) {
                this.SaveNewTransaction();
                return true;
            }
            else return false;

        }

        /// <summary>
        /// Zapis nowego płatności do bazy. Zapis nowej tranzakcji
        /// </summary>
        private void SaveNewTransaction() {

            this.transaction = new PaymentTransaction(Session.SessionID + "-" + reservation.ReservationId,
                this.GetReservationTotalCost(),
                "Rezerwacja " + reservation.ReservationNumber + " w Aparts Bed&Breakfast",
                reservation.Client.FirstName,
                reservation.Client.LastName,
                reservation.Client.EMail,
                this.GetUserIP());

            this.transaction.OrderId = this.reservation.ReservationId;
            this.transaction.Country = new Currency(0, this.reservation.Client.PrefferCurrency).Code.LCID.First().TwoLetterISOLanguageName; // pobranie kraju na podstawie preferowanej waluty
            this.transaction.DescriptionExtension = string.Format("Klient: {0} {1}, Rezerwacja: {2}", this.reservation.Client.FirstName, this.reservation.Client.LastName, this.reservation.ReservationNumber);
            this.transaction.Language = CultureInfo.CurrentCulture.TwoLetterISOLanguageName;
            this.transaction.SaveNew();
        }

        public double GetReservationTotalCost() {
            ReservationAdditionalServicesOrder servicesOrder = this.GetReservationAdditionalServicesOrder(reservation);
            return Math.Round(reservation.FinalPrice + servicesOrder.Value, 2);
        }

        private ReservationAdditionalServicesOrder GetReservationAdditionalServicesOrder(IWebReservation reservation) {
            ReservationAdditionalServicesOrder order = null;
            if (HttpContext.Current != null) {
                Page page = HttpContext.Current.Handler as Page;
                if (page != null && page.Items.Contains("ReservationAdditionalServicesOrder-" + reservation.ReservationId)) {
                    order = page.Items["ReservationAdditionalServicesOrder-" + reservation.ReservationId] as ReservationAdditionalServicesOrder;
                }
            }
            if (order == null) {
                order = new ReservationAdditionalServicesOrder(reservation);
                if (HttpContext.Current != null) {
                    Page page = HttpContext.Current.Handler as Page;
                    if (page != null)
                        page.Items.Add("ReservationAdditionalServicesOrder-" + reservation.ReservationId, order);
                }
            }
            return order;
        }

        public string GetUserIP() {
            string ipList = Request.ServerVariables["HTTP_X_FORWARDED_FOR"];
            if (!string.IsNullOrEmpty(ipList)) {
                return ipList.Split(',')[0];
            }
            return Request.ServerVariables["REMOTE_ADDR"];
        }

        private bool SetScenarioForPayments() {
            if (this.SetReservationFromRequest()) {
                this.paymentTypes = factory.GetPaymentType().GetWebPayments();
                if (paymentTypes.Length > 0) {
                    this.paymentTypes = this.paymentTypes.OrderByDescending(pt => pt.ExtraRabat).ToArray();
                    ReservationServices services = new ReservationServices(this.reservation);
                    this.additionalServicesCost = services.TotalCost;
                    return true;
                }
            }
            return false;
        }

        private bool SetScenarioForContact() {
            return this.SetReservationFromRequest();
        }

        private bool SetScenarioForStatus() {
            if (this.SetReservationFromRequest()) {
                IApartment apartment = this.factory.GetApartment(this.reservation.ApartmentReservation.First().ApartmentId);
                if (apartment != null && apartment.Group != null && apartment.Group.Id > 0) {
                    this.statusApartmentGroup = apartment.Group;
                    this.statusMaxPersons = this.statusApartmentGroup.NumberOfPeople * this.reservation.ApartmentReservation.Length;
                    return true;
                }
            }
            return false;
        }

        private bool SetScenarioForInformation() {
            SearchState state = SearchState.GetFromContext();
            int groupId = 0;
            if (!state.IsSet || !Int32.TryParse(Request["apartment"], out groupId) || groupId == 0)
                return false;

            FreeApartments search = state.GetSearchVariants();
            search.FilterToApartmentType(groupId);
            this.variant = search.FirstOrDefault();
            if (this.variant == null)
                return false;

            IPriceRabat webRabat = this.factory.GetPriceRabat().GetRabat("web");
            if (webRabat != null)
                this.variant.Price.ApplyPriceRabat(webRabat);
            return true;
        }

        private void PopulateView() {
            if (error) {
                this.PopulateErrorView();
                return;
            }
            this.SetPageSeo();
            if (Request.QueryString["step"] == PARAM_INFORMATION)
                this.PopulateInformationView();
            if (Request.QueryString["step"] == PARAM_CONTACT)
                this.PopulateContactView();
            if (Request.QueryString["step"] == PARAM_SERVICES)
                this.PopulateAdditionalServices();
            if (Request.QueryString["step"] == PARAM_PAYMENT)
                this.PopulatePaymentView();
            if (Request.QueryString["step"] == PARAM_END)
                this.PopulateEndView();
            if (Request.QueryString["step"] == PARAM_CONFIRM)
                this.PopulateConfirmView();
            if (Request.QueryString["step"] == PARAM_PAY)
                this.PopulatePayProcessView();
            if (Request.QueryString["step"] == PARAM_STATUS)
                this.PopulateStatusView();

            JQueryLibraries jql = new JQueryLibraries();
            jql.IncludeFileBasedOnJQuery("blackhouse.Aparts.Web.Scripts.web-reservation.js,blackhouse.Aparts.Web");
        }

        private void PopulateEndView() {
            this.SetReservationCrumbs(4);
            this.ltlReservationClientEmail.Text = this.reservation.Client.EMail;
            this.ltlReservationNumber.Text = this.reservation.ReservationNumber;
            this.lnkReservationStatus.NavigateUrl = NavigationProvider.Instance().GetUrl(ReservationPage.GetStatusPage(this.reservation));
            if (this.breadcrumb != null)
                this.breadcrumb.AddCrumb(GetGlobalResourceObject("Aparts", "completeBooking").ToString(), "");
            this.mvView.SetActiveView(vEnd);
        }

        private void PopulateConfirmView() {
            this.SetAlternativeTitle(GetGlobalResourceObject("Aparts", "confirmBookingText") + " " + this.reservation.ReservationNumber);
            this.lnkDisplayReservation.Text = string.Format(this.lnkDisplayReservation.Text, this.reservation.ReservationNumber);
            this.lnkDisplayReservation.NavigateUrl = NavigationProvider.Instance().GetUrl(ReservationPage.GetStatusPage(this.reservation));
            if (this.reservation.PaymentType.Key == "payu") {
                this.pnlOnlinePayment.Visible = true;
                this.lnkToPayment.NavigateUrl = NavigationProvider.Instance().GetUrl(ReservationPage.GetProcessPayPage(this.reservation));
            }
            this.mvView.SetActiveView(vConfirm);
        }

        private void PopulatePayProcessView() {
            this.SetAlternativeTitle("Płatność za rezerwację " + this.reservation.ReservationNumber);
            this.transactionForm.Transaction = this.transaction;
            this.mvView.SetActiveView(vPayU);
        }

        private void PopulatePaymentView() {
            this.SetReservationCrumbs(4);
            this.rptPayments.DataSource = this.paymentTypes;
            this.rptPayments.DataBind();

            this.curReservationCostAbPayment.Value = this.reservationPriceCalculator.ReservationCost;
            this.curTotalReservationCost.Value = this.reservationPriceCalculator.TotalCost;
            if (additionalServicesCost > 0) {
                this.pnlPaymentAdditionalServicesInfo.Visible = true;
                this.phPaymentAdditionalServicesInfo2.Visible = true;
                this.pnlPaymentAdditionalServicesInfo3.Visible = true;
                this.curReservationAdditionalServicesCost.Value = this.additionalServicesCost;
            }
            if (this.breadcrumb != null)
                this.breadcrumb.AddCrumb(GetGlobalResourceObject("Aparts", "paymentType").ToString(), "");
            this.mvView.SetActiveView(this.vPayment);
        }

        private void PopulateAdditionalServices() {
            this.SetReservationCrumbs(3);
            this.rptServices.DataSource = this.additionalServices;
            this.rptServices.DataBind();
            this.mvView.SetActiveView(this.vAdditionalServices);
            this.curReservationCost.Value = this.reservationPriceCalculator.ReservationCost;
            this.curReservationCost2.Value = this.reservationPriceCalculator.ReservationCost;
            this.reservationCost.Value = this.reservationPriceCalculator.ReservationCost.ToString("F2", CultureInfo.InvariantCulture);
            if (this.breadcrumb != null)
                this.breadcrumb.AddCrumb(GetGlobalResourceObject("Aparts", "additionalServices").ToString(), "");
            this.lnkGoToPayments.Text = GetGlobalResourceObject("Aparts", "gotoStep") + ":<br />" + GetGlobalResourceObject("Aparts", "paymentType");

        }

        private void PopulateContactView() {
            this.SetReservationCrumbs(2);
            if (this.breadcrumb != null)
                this.breadcrumb.AddCrumb(GetGlobalResourceObject("Aparts", "contactDetails").ToString(), "");
            PageProvider pp = new PageProvider();
            mojoPortal.Business.PageSettings p = pp.FindCmsPageByFunctionality("policy");
            if (p != null)
                this.lnkPrivatePolicy.NavigateUrl = p.Url;
            else
                this.lnkPrivatePolicy.Visible = false;
            this.lblNextDayArrival.Style.Add(HtmlTextWriterStyle.Display, "none");
            this.lblNextDayArrival.Text = this.reservation.ArrivalDate.AddDays(1).ToString("D");
            this.lnkContactComplete.Text = GetGlobalResourceObject("Aparts", "gotoStep") + ":<br />" + GetGlobalResourceObject("Aparts", "additionalServices");

            this.mvView.SetActiveView(this.vReservationClient);
        }

        private void PopulateInformationView() {
            this.SetReservationCrumbs(1);
            this.ltlApartmentsCount.Text = variant.ApartmentCount.ToString();
            if (variant.ApartmentCount > 1) {
                this.lblLpApartmentsCount.Visible = false;
                this.lblMpApartmentsCount.Visible = true;
            }
            this.lblApartmentName.Text = this.variant.GetGroups().First().ShortName;
            int numberOfPeoples = this.variant.Items.Sum(i => i.NumberOfPeoples);
            int maxNumberOfPeoples = this.variant.GetGroups().Sum(g => g.NumberOfPeople);
            this.lblNumberPeoples.Text = numberOfPeoples.ToString();
            this.lblPeoples.Text = this.GetPersonText(numberOfPeoples);
            this.lblMaxNumberPeoples.Text = maxNumberOfPeoples + " " + this.GetPersonText(maxNumberOfPeoples);
            this.lblArrivalDate.Text = this.variant.Items[0].ArrivalDate.ToString("d MMMM yyyy");
            this.lblDepartureDate.Text = this.variant.Items[0].DepartureDate.ToString("d MMMM yyyy");
            this.lblPrice.Value = this.variant.Price.GetPrice();
            this.lblPreviousPrice.Value = this.variant.Price.GetPriceWithoutRabat();
            if (this.variant.Price.GetRabatValue() != 0) {
                IPriceRabat[] rabats = this.variant.Price.GetAssociacedRabats();
                string[] rNames = new string[rabats.Length];
                string[] rValues = new string[rabats.Length];
                for (int xr = 0; xr < rabats.Length; xr++) {
                    rNames[xr] = rabats[xr].RabatName + ":";
                    rValues[xr] = string.Format("{0:F0}%", rabats[xr].RabatValue);
                }
                this.ltlDiscounts.Text = String.Join("<br />", rNames);
                this.ltlDiscountsValue.Text = String.Join("<br />", rValues);
            }
            if (this.breadcrumb != null)
                this.breadcrumb.AddCrumb(GetGlobalResourceObject("Aparts", "informationToBook").ToFirstUpperString(), "");
            this.lnkGotoContact.Text = GetGlobalResourceObject("Aparts", "gotoStep") + ":<br />" + GetGlobalResourceObject("Aparts", "contactDetails");
            this.mvView.SetActiveView(this.vReservationInfo);
        }

        private void PopulateStatusView() {
            this.SetAlternativeTitle(GetGlobalResourceObject("Aparts", "bookingStatus") + " " + this.reservation.ReservationNumber);
            this.ltlStatusApartmentsCount.Text = this.reservation.ApartmentReservation.Length.ToString();
            if (this.reservation.ApartmentReservation.Length > 1) {
                this.lblStatusLpApartmentsCount.Visible = false;
                this.lblStatusMpApartmentsCount.Visible = true;
            }
            this.lblStatusApartmentName.Text = this.statusApartmentGroup.Name;
            this.lblStatusNumberPeoples.Text = this.reservation.PersonCount.ToString();
            this.lblStatusPeoples.Text = this.GetPersonText(this.reservation.PersonCount);
            this.lblStatusMaxNumberPeoples.Text = this.statusMaxPersons + " " + this.GetPersonText(this.statusMaxPersons);
            this.lblStatusArrivalDate.Text = this.reservation.ArrivalDate.ToString("d MMMM yyyy");
            this.lblStatusDepartureDate.Text = this.reservation.DepartureDate.ToString("d MMMM yyyy");
            this.lblStatusPrice.Value = GetReservationTotalCost();

            this.ltlStatusReservationNumber.Text = this.reservation.ReservationNumber;
            this.ltlStatusName.Text = this.reservation.Status.Name;
            this.ltlStatusDescription.Text = this.reservation.Status.Description;

            ReservationAdditionalServicesOrder servicesOrder = this.GetReservationAdditionalServicesOrder(this.reservation);
            if (servicesOrder.Value > 0) {
                this.rptOrderAdditionalServices.DataSource = servicesOrder.GetOrderingReservationServices();
                this.rptOrderAdditionalServices.DataBind();
            }
            else
                this.rptOrderAdditionalServices.Visible = false;

            this.mvView.SetActiveView(this.vStatus);
        }

        protected void rptOrderAdditionalServices_ItemDataBound(object sender, RepeaterItemEventArgs e) {
            switch (e.Item.ItemType) {
                case ListItemType.AlternatingItem:
                case ListItemType.Item:
                    ReservationAdditionalService service = e.Item.DataItem as ReservationAdditionalService;
                    CurrencyLiteral ltlUnitPrice = e.Item.FindControl("ltlUnitPrice") as CurrencyLiteral;
                    CurrencyLiteral ltlCost = e.Item.FindControl("ltlCost") as CurrencyLiteral;
                    if (service != null) {
                        if (ltlUnitPrice != null)
                            ltlUnitPrice.Value = service.Service.UnitPrice;
                        if (ltlCost != null)
                            ltlCost.Value = service.Price;
                    }
                    break;
                case ListItemType.Footer:
                    ReservationAdditionalServicesOrder servicesOrder = this.GetReservationAdditionalServicesOrder(this.reservation);
                    Literal ltlTotalQuantity = e.Item.FindControl("ltlTotalQuantity") as Literal;
                    CurrencyLiteral ltlTotalCost = e.Item.FindControl("ltlTotalCost") as CurrencyLiteral;
                    if (ltlTotalQuantity != null) {
                        ltlTotalQuantity.Text = servicesOrder.GetOrderingReservationServices().Sum(ras => ras.Quantity).ToString();
                        ltlTotalCost.Value = servicesOrder.Value;
                    }
                    break;
            }
        }

        private string GetPersonText(int persons) {
            string key = "";
            if (persons == 1)
                key = "personOne";
            else if ((persons > 1 && persons <= 4) || (persons > 20 && persons % 10 > 1 && persons % 10 <= 4))
                key = "personMoreOne";
            else
                key = "personMany";
            return GetGlobalResourceObject("Aparts", key).ToString();
        }

        private void PopulateErrorView() {
            this.mvView.SetActiveView(this.vUnavalible);
        }

        #endregion

        #region Methods

        private void SetAlternativeTitle(string title) {
            this.ltlReservationOnline.Visible = false;
            this.ltlAlternativeTitle.Text = title;
            this.ltlAlternativeTitle.Visible = true;
        }

        private void SetReservationCrumbs(int crumbPageNumber) {
            this.pnlReservationCrumbs.Visible = true;
            this.lblPageNumber.Text = crumbPageNumber.ToString();
            this.activePage = crumbPageNumber;
        }

        #endregion

        protected void lnkGotoContact_Click(object sender, EventArgs e) {
            this.SetScenarioForInformation(); // Refresh informacji z ekranu
            if (this.variant == null || this.variant.Items.Length == 0) {
                Response.Redirect(NavigationProvider.Instance().GetUrl(SearchState.Empty));
                return;
            }
            IWebReservation reservation = this.factory.CreateWebReservation();
            foreach (VariantItem item in this.variant.Items) {
                reservation.AddApartment(item.Apartment.Id, item.NumberOfPeoples);
            }
            reservation.SetDates(this.variant.Items[0].ArrivalDate, this.variant.Items[0].DepartureDate);
            reservation.SetPrice(this.variant.Price);

            reservation.Save();
            Response.Redirect(NavigationProvider.Instance().GetUrl(ReservationPage.GetContactPage(reservation)));
        }

        protected void lnkContactComplete_Click(object sender, EventArgs e) {
            if (Page.IsValid) {
                this.SetScenarioForContact();
                string email = Request[this.txtEMail.UniqueID];
                string firstName = Request[this.txtFirstName.UniqueID];
                string lastName = Request[this.txtLastName.UniqueID];
                string phone = Request[this.txtPhone.UniqueID];
                string comments = Request[this.txtOverview.UniqueID];
                string arrivalTime = Request[this.txtArrivalTime.UniqueID];

                IClient client = factory.GetClient(0).SearchClientByEmail(email);
                client.EMail = email;
                client.FirstName = firstName;
                client.LastName = lastName;
                client.PhoneNumber = phone;
                client.PrefferCurrency = DisplayCurrency.GetUserCurrency();
                client.PersonTitle = "p.";
                if (client.Save()) {

                    this.reservation.SetClient(client);

                    string[] timeParts = arrivalTime.Split(':');
                    int hour, minutes;
                    hour = Int32.Parse(timeParts[0]);
                    minutes = Int32.Parse(timeParts[1]);
                    if (hour < 14)
                        hour += 24;

                    this.reservation.SetArrivalTime(TimeSpan.FromMinutes(hour * 60 + minutes));
                    this.reservation.Comments = comments;
                    if (this.reservation.Save())
                        Response.Redirect(NavigationProvider.Instance().GetUrl(ReservationPage.GetServicesPage(reservation)));
                }
            }
        }

        protected void rptServices_ItemDataBound(object sender, RepeaterItemEventArgs e) {
            switch (e.Item.ItemType) {
                case ListItemType.AlternatingItem:
                case ListItemType.Item:
                    IAdditionalService service = e.Item.DataItem as IAdditionalService;
                    if (service == null) {
                        this.Visible = false;
                        return;
                    }
                    Panel pnlLine = e.Item.FindControl("pnlLine") as Panel;


                    // Wybieramy odpowiednią kontrolkę do zamawiania usługi

                    Control cView = e.Item.FindControl("editablePer" + this.GetViewVariant(service.ServiceFor));
                    IReservationAdditionalServiceView view = cView as IReservationAdditionalServiceView;
                    if (view == null) {
                        e.Item.Visible = false;
                        return;
                    }

                    cView.Visible = true;

                    view.Days = (int)(this.reservation.DepartureDate.Date - this.reservation.ArrivalDate.Date).TotalDays;
                    DisplayCurrency currency = new DisplayCurrency(service.UnitPrice, 2);
                    currency.Load();
                    view.UnitPrice = currency.Currency;
                    double val = service.UnitPrice; // Wartość dla szybkiego zamówienia (OneClick)
                    if ((service.ServiceFor & ServiceFor.Day) == ServiceFor.Day) {
                        val = val * view.Days; // usługa każdego dnia
                        if ((service.ServiceFor & ServiceFor.Quantity) == ServiceFor.Quantity) {
                            int q = reservation.PersonCount;// każdego dnia tyle x usług ile osób na rezerwacji
                            if (service.DefaultQuantity > 0)
                                q = service.DefaultQuantity;
                            val = val * q;
                        }
                    }

                    currency = new DisplayCurrency(val, 2);
                    currency.Load();
                    view.Value = currency.Currency;
                    view.Load(this.reservation, service);
                    if (pnlLine != null) {
                        view.RegisterClientUI(pnlLine);
                        HiddenField hf = new HiddenField();
                        hf.ID = "unitprice";
                        hf.Value = view.UnitPrice.Value.ToString("F2", CultureInfo.InvariantCulture);
                        pnlLine.Controls.Add(hf);
                    }
                    break;
            }
        }

        private string GetViewVariant(ServiceFor serviceFor) {
            if (serviceFor == ServiceFor.None)
                return "Room";
            else {
                if ((serviceFor & ServiceFor.Room) == ServiceFor.Room) {
                    if (this.reservation.ApartmentReservation.Length == 1) {
                        return this.GetViewVariant(serviceFor ^ ServiceFor.Room);
                    }
                    else
                        return string.Empty;
                }
                else {
                    if ((serviceFor & ServiceFor.Day) == ServiceFor.Day) {
                        if ((serviceFor & ServiceFor.Quantity) == ServiceFor.Quantity)
                            return "Person";
                        else
                            return "Night";
                    }
                    else
                        return string.Empty;
                }
            }
        }

        protected void lnkGoToPayments_Click(object sender, EventArgs e) {
            this.SetScenarioForAdditionalServices();
            this.PopulateAdditionalServices();

            foreach (RepeaterItem item in this.rptServices.Items) {
                if (!item.Visible) continue;
                switch (item.ItemType) {
                    case ListItemType.AlternatingItem:
                    case ListItemType.Item:
                        Control cView = null;
                        foreach (string sf in new string[] { "Room", "Night", "Person" }) {
                            cView = item.FindControl("editablePer" + sf);
                            if (cView != null && cView.Visible)
                                break;
                        }
                        if (cView != null) {
                            IReservationAdditionalServiceView view = cView as IReservationAdditionalServiceView;
                            if (view != null) {
                                view.ReceiveSave();
                            }
                        }
                        break;
                }
            }
            Response.Redirect(NavigationProvider.Instance().GetUrl(ReservationPage.GetPaymentPage(reservation)));
        }

        protected void rptPayments_ItemDataBound(object sender, RepeaterItemEventArgs e) {
            switch (e.Item.ItemType) {
                case ListItemType.AlternatingItem:
                case ListItemType.Item:
                    IPaymentType paymentType = e.Item.DataItem as IPaymentType;
                    HiddenField rabatPriceValue = e.Item.FindControl("rabatPriceValue") as HiddenField;
                    HiddenField reservationValueWithRabat = e.Item.FindControl("reservationValueWithRabat") as HiddenField;
                    if (paymentType != null) {
                        DisplayCurrency dc = new DisplayCurrency();
                        string currencyCode = dc.GetCurrentCurrency();
                        double rabatValue = this.reservation.Price * paymentType.ExtraRabat / 100;
                        double reservationPriceWithRabat = this.reservationPriceCalculator.TotalCost + rabatValue;
                        Currency curRabatPriceValue = new Currency(rabatValue, "PLN", 2);
                        Currency curReservationPriceWithRabat = new Currency(reservationPriceWithRabat, "PLN", 2);
                        if (rabatPriceValue != null)
                            rabatPriceValue.Value = curRabatPriceValue.ToCurrency(currencyCode).ToString();
                        if (reservationValueWithRabat != null)
                            reservationValueWithRabat.Value = curReservationPriceWithRabat.ToCurrency(currencyCode).ToString();
                    }
                    break;
            }
        }

        protected void lnkEndReservation_Click(object sender, EventArgs e) {
            string paymentKey = Request["payment_type"];
            if (string.IsNullOrEmpty(paymentKey) || !this.SetScenarioForPayments()) {
                this.PopulateErrorView();
                return;
            }
            IPaymentType paymentType = this.factory.GetPaymentType().GetWebPayments().FirstOrDefault(p => p.Key == paymentKey);
            if (paymentType == null) {
                this.PopulateErrorView();
                return;
            }
            this.reservation.SetPaymentType(paymentType);
            this.reservation.ChangeStatus("initial");
            Response.Redirect(NavigationProvider.Instance().GetUrl(ReservationPage.GetEndPage(reservation)));
        }

    }
}